const {SyncHook} = require("tapable")
const Complilation = require("./Complilation")
const fs = require("fs")
const mkdirp = require("mkdirp")
const path = require("path")
module.exports =  class Compiler{
  constructor(options){
    this.options = options;
    this.assets = {}
    this.hooks = {
      initialize: new SyncHook(["args"]),
      compile:new SyncHook(["agrs"]),
      emit:new SyncHook(["agrs"]),
      done:new SyncHook(["agrs"])
    }

    this.bindHooks();

    this.hooks.initialize.call(this.options);
  }

  bindHooks(){
    const {plugins} = this.options;
    if(plugins && Array.isArray(plugins)){
      plugins.forEach(p=>{
        p.apply.call(p,this)
      })
    }
  }

  run(){
    this.hooks.compile.call(this.options);

    //查找依赖模块
    this.complilation = new Complilation(this.options,this);
    this.modules = this.complilation.buildModules();


    this.hooks.emit.call();
    this.emit();
    this.hooks.done.call();
  };

  emit(){
    const code = `
    ;(function(entry,modules){
      function require(pathname){
        var module = {
          exports:{}
        };
        (function(require,module,exports){
          const code = modules[pathname].code;
          try{
            // console.log(code)
            eval(code)
          }catch(err){
            console.log(err,22222)
          }
        })(require,module,module.exports);
        return module.exports;
      }
      require(entry)
    })(${JSON.stringify(this.options.entry)},${JSON.stringify(this.modules)})
    `;
    // console.log(this.modules)
    // console.log(code)
    this.assets[this.options.output.filename] = code;

    //创建文件夹
    
    if(!fs.existsSync(this.options.output.path)){
      fs.mkdirSync(this.options.output.path)
    }

    const outputFiles = Object.keys(this.assets)
    outputFiles.forEach(filename =>{
      const absolutePath = filename.startsWith('/') ? filename :path.join(this.options.output.path,filename)
      
      const dirname = path.dirname(absolutePath);
      if(!fs.existsSync(dirname)){
        mkdirp(dirname)
      }

      fs.writeFileSync(absolutePath,this.assets[filename]);
    })
  };
}